﻿using System;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Windows.Input;

namespace Gmantis.Controls
{
    public sealed class CommandConverter : TypeConverter
    {
        // Methods
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return (sourceType == typeof(string));
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return (destinationType == typeof(string));
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object source)
        {
            if ((source != null) && (source is string))
            {
                string str;
                string str2;
                if (((string)source) == string.Empty)
                {
                    return null;
                }
                this.ParseUri((string)source, out str, out str2);
                ICommand command = ConvertFromHelper(this.GetTypeFromContext(context, str), str2);
                if (command != null)
                {
                    return command;
                }
            }
            return source;
        }

        internal static ICommand ConvertFromHelper(Type ownerType, string localName)
        {
            ICommand command = null;
            if (ownerType != null)
            {
                PropertyInfo property = ownerType.GetProperty(localName, BindingFlags.Public | BindingFlags.Static);
                if (property != null)
                {
                    command = property.GetValue(null, null) as ICommand;
                }
                if (command == null)
                {
                    FieldInfo field = ownerType.GetField(localName, BindingFlags.Public | BindingFlags.Static);
                    if (field != null)
                    {
                        command = field.GetValue(null) as ICommand;
                    }
                }
            }
            return command;
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == null)
            {
                throw new ArgumentNullException("destinationType");
            }
            if (destinationType == typeof(string))
            {
                if (value == null)
                {
                    return string.Empty;
                }
                Command command = value as Command;
                if (command != null)
                {
                    return command.ToString();
                }
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

        private Type GetTypeFromContext(ITypeDescriptorContext context, string typeName)
        {
            return CommandManager.GetRegisteredType(typeName);
        }

        private void ParseUri(string source, out string typeName, out string localName)
        {
            typeName = null;
            localName = source.Trim();
            int length = localName.LastIndexOf(".", StringComparison.Ordinal);
            if (length >= 0)
            {
                typeName = localName.Substring(0, length);
                localName = localName.Substring(length + 1);
            }
        }
    }
}
